#pragma once
#include<Wire.h>

namespace ganix {
    namespace wire {
        bool _wire_inited = false;
        int _sda = -1;
        int _scl = -1;
        int _addr = -1;
        bool _specified_pin = false;

        void set_pin(int sda, int scl) {
            _sda = sda;
            _scl = scl;
            _specified_pin = (sda != -1 && scl != -1);
        }

        void as_slave(int addr, void (*on_receive)(int), void (*on_request)(void)) {
            Wire.onReceive(on_receive);
            Wire.onRequest(on_request);
            _addr = addr;
        }

        void flush_pin() {
            if (_specified_pin) {
                if (_addr == -1) {
                    Wire.begin(_sda, _scl);
                } else {
                    Wire.begin(_sda, _scl, _addr);
                }
            } else {
                if (_addr == -1) {
                    Wire.begin();
                } else {
                    Wire.begin(_addr);
                }
            }
        }

        void i2c_init() {
            if (!_wire_inited) {
                flush_pin();
                _wire_inited = true;
            }
        }

        void i2c_send(uint8_t addr, const uint8_t *buf, int cnt = 1) {
            Wire.beginTransmission(addr);
            Wire.write(buf, cnt);
            Wire.endTransmission();  
        }

        uint8_t i2c_recv(uint8_t addr, uint8_t *buf, int cnt) {
            int rtn = 0;
            Wire.beginTransmission(addr);
            Wire.requestFrom(addr, cnt);
            while (rtn < cnt && Wire.available()) {
                buf[rtn++] = Wire.read();
            }
            Wire.endTransmission();
            return rtn;
        }
    } // namespace wire
} // namespace ganix
